package com.worklikedance.priceonline;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.AttributeSet;
import com.worklikedance.util.Log;
import android.util.Xml;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.worklikedance.model.ExchangeRateItem;
import com.worklikedance.priceonline.R.color;
import com.worklikedance.util.Constant;
import com.worklikedance.util.CustomConnection;
import com.worklikedance.util.FetchingCode;
import com.worklikedance.util.PopoverView;
import com.worklikedance.util.PopoverView.PopoverViewDelegate;
import com.worklikedance.util.Utilities;

public class ExchangedRate extends RelativeLayoutEx implements PopoverViewDelegate {
	private ExchangedRateAdapter mCurrAdapter;	

	private String mPrevUpdatedDateTime = "";
	
	//
	private ArrayList<ExchangeRateItem> mCurrExchangeRateArray = null;
	private ArrayList<ExchangeRateItem> mPreExchangeRateArray = null;

	public ExchangedRate(Context context) {
		this(context, null);		
	}

	public ExchangedRate(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	
	public ExchangedRate(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		
		mLatestUpadateDateTime = Utilities.getData(Constant.LATEST_RATE_TIME_KEY, getContext());
		
		// Get a reference to the ListView holder
		mPullToRefreshListView = (PullToRefreshListView) this.findViewById(R.id.rate_list);
		mPullToRefreshListView.getLoadingLayoutProxy().setPullLabel( getResources().getString(R.string.pull_to_refresh_label) );
		mPullToRefreshListView.getLoadingLayoutProxy().setRefreshingLabel( getResources().getString(R.string.updating_title) );
		mPullToRefreshListView.getLoadingLayoutProxy().setReleaseLabel( getResources().getString(R.string.pull_to_refresh_label) );
		mPullToRefreshListView.getLoadingLayoutProxy().setLastUpdatedLabel("");

		mUpdatedTimeTextView = (TextView) this.findViewById(R.id.update_status_value);

		// Set the adapter on the ListView holder
		ArrayList<ExchangeRateItem> rateArray = new ArrayList<ExchangeRateItem>();

		// Set a listener to be invoked when the list should be refreshed.
		mPullToRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
			@Override
			public void onRefresh(PullToRefreshBase<ListView> refreshView) {
				// Do work to refresh the list here.
//				new GetDataTask().execute(Constant.EXCHANGE_RATE_URL);
				
				mManualFetchingData = true;
				fetchData(false);
			}
		});

		mListView = mPullToRefreshListView.getRefreshableView();
		mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

		// Need to use the Actual ListView when registering for Context Menu
		if (mCurrAdapter == null) {			
			mCurrAdapter = new ExchangedRateAdapter(mContext, rateArray, null);

			mListView.setAdapter(mCurrAdapter);

			showWaitingProgress(getResources().getString(R.string.updating_title));

			mManualFetchingData = true;
			fetchData(true);
		}
		else {
			mListView.setAdapter(mCurrAdapter);
			mCurrAdapter.notifyDataSetChanged();			
		}		
		
		mListView.setOnItemClickListener(new OnItemClickListener() {
			
			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int position,
					long arg3) {
				if (MainActivity.getInstance() != null) {
					MainActivity.getInstance().dismissPopup();
				}
				
//				mListView.setItemChecked(position, true);
				
				//position start from 1
				position -= 1;
				
				RelativeLayout rootView = ExchangedRate.this;
				mPopoverView = new PopoverView(mContext, R.layout.popover_exchange_rate_view);

				int width = view.getWidth();
				int height = Utilities.getDP(mContext, 110);
				
				mPopoverView.mRowIndex = position;
				mPopoverView.setContentSizeForViewInPopover(new Point(width, height));
				mPopoverView.setDelegate(ExchangedRate.this);
				mPopoverView.showPopoverFromRectInViewGroup(rootView, PopoverView.getFrameForView(view), PopoverView.PopoverArrowDirectionAny, true);
			}
		});				
	}

	@Override
	public void fetchData(boolean allowLoadingOfflineData) {
		if (mFetchingData == true) {
			Log.d("GoldPrice", "Keep fetchData - Fetching task is running");
			
			return;
		}
		
		Log.d("GoldPrice", "Start fetchData ex rate");
		mFetchingData = true;
		
		String allowLoadingOfflineDataString = "false";
		if (allowLoadingOfflineData) {
			allowLoadingOfflineDataString = "true";
		}

		String uri = Utilities.getUri( getResources().getString(R.string.exchange_rate_l) );
		new FetchExchangeRateTask().execute(uri, allowLoadingOfflineDataString);
	}
	
	private class FetchExchangeRateTask extends AsyncTask<String, Void, Integer> {
		String updateTime = "";
		String prevUpdatedTime = "";
		
		ArrayList<ExchangeRateItem> exchangeRateArray = null;
		ArrayList<ExchangeRateItem> prevExchangeRateArray = null;
		
		@Override
		protected Integer doInBackground(String... params) {
			boolean allowLoadingOfflineData = Boolean.parseBoolean(params[1]);
			boolean loadedOfflineData = false;
			boolean initData = false;
			
			String xmlDocument = "";
			
			try {
				xmlDocument = CustomConnection.executeHttpGet(params[0]);
			} 
			catch (Exception e) {
				e.printStackTrace();

				if (allowLoadingOfflineData) {
					xmlDocument = Utilities.getData(Constant.LATEST_RATE_KEY, mContext);
					loadedOfflineData = true;
				}
				else {
					return FetchingCode.NoNetwork.ordinal();
				}
			}

			try {
				ExchangedRateXMLHandler exchangeRateXMLHandler = new ExchangedRateXMLHandler();
				Xml.parse(xmlDocument, exchangeRateXMLHandler);
				
				updateTime = exchangeRateXMLHandler.getmUpdateTime();
				if (updateTime == null || updateTime.length() == 0) {
					return FetchingCode.InvalidFormat.ordinal();
				}
				
				Date updateDateTime = Utilities.convertStringToDate(updateTime, Constant.UPDATED_DATE_TIME_FORMAT);
				
				if (mLatestUpadateDateTime != null && mLatestUpadateDateTime.length() > 0) {
					Date updatedDateTime = Utilities.convertStringToDate(mLatestUpadateDateTime, Constant.UPDATED_DATE_TIME_FORMAT);
					
					if (Utilities.compareDateWithoutSecond(updateDateTime, updatedDateTime) <= 0) {
						if (mCurrExchangeRateArray != null) {
							return FetchingCode.SameData.ordinal();	
						}
						
						initData = true;
						
						// Parse saved data
						if (loadedOfflineData == false) {
							xmlDocument = Utilities.getData(Constant.LATEST_RATE_KEY, mContext);
							updateTime = mLatestUpadateDateTime;
						}
					}
					
					prevExchangeRateArray = mCurrExchangeRateArray;
					prevUpdatedTime = mLatestUpadateDateTime;
				}
				
				exchangeRateArray = exchangeRateXMLHandler.getmRateArray();

				if (exchangeRateArray != null) {
//					Collections.sort(exchangeRateArray, new ExchangeRateComparator());
					
					for (int i = 0; i < exchangeRateArray.size(); i ++) {
						ExchangeRateItem exRate = exchangeRateArray.get(i);
						
						if (exRate == null) {
							continue;
						}
						
						String code = exRate.getCurrencyCode();
						if (code != null && code.equalsIgnoreCase("USD")) {
							if (i == 0) {
								break;
							}
							
							exchangeRateArray.remove(exRate);
							exchangeRateArray.add(0, exRate);
							
							break;
						}
					}
				}
				
				if (loadedOfflineData == false && initData == false) {
					String xmlPriceTmp = Utilities.getData(Constant.LATEST_RATE_KEY, mContext);
					
					Utilities.storeData(Constant.LATEST_RATE_KEY, xmlDocument, mContext);
					Utilities.storeData(Constant.LATEST_RATE_TIME_KEY, updateTime, mContext);					

					if ( xmlPriceTmp != null && xmlPriceTmp.length() > 0 ) {
						Utilities.storeData(Constant.OLD_RATE_KEY, xmlPriceTmp, mContext);	
					}
				}
				
				if (prevExchangeRateArray == null) {
					String prevXmlDocument = Utilities.getData(Constant.OLD_RATE_KEY, mContext);
					
					if (prevXmlDocument != null && prevXmlDocument.length() > 0) {
						ExchangedRateXMLHandler prevExchangeRateXMLHandler = new ExchangedRateXMLHandler();
						Xml.parse(prevXmlDocument, prevExchangeRateXMLHandler);

						prevExchangeRateArray = prevExchangeRateXMLHandler.getmRateArray();
						prevUpdatedTime = prevExchangeRateXMLHandler.getmUpdateTime();
					}
					else {
						prevExchangeRateArray = null;
						prevUpdatedTime = "";
					}
				}

				if (prevExchangeRateArray != null) {
//					Collections.sort(prevExchangeRateArray, new ExchangeRateComparator());
					
					for (int i = 0; i < prevExchangeRateArray.size(); i ++) {
						ExchangeRateItem exRate = prevExchangeRateArray.get(i);
						
						if (exRate == null) {
							continue;
						}
						
						String code = exRate.getCurrencyCode();
						if (code != null && code.equalsIgnoreCase("USD")) {
							if (i == 0) {
								break;
							}
							
							prevExchangeRateArray.remove(exRate);
							prevExchangeRateArray.add(0, exRate);
							
							break;
						}
					}
				}
			} 
			catch (Exception e) {
				return FetchingCode.Failed.ordinal();
			}
			
			return FetchingCode.Success.ordinal();
		}

		@Override
		protected void onPostExecute(Integer result) {
			Log.d("ExchangeRate", "Finish fetchData ex rate, code: " + result);
			
			mFetchingData = false;
			
			if (ExchangedRate.this != null) {
				hideWaitingProgress();	
			}
			
			if (mPullToRefreshListView != null) {
				mPullToRefreshListView.onRefreshComplete();	
			}
			
			if (mManualFetchingData && mContext != null) {
				if (result == FetchingCode.SameData.ordinal()) {
					alert(mContext.getString(R.string.ty_gia_moi_nhat));
				}
				else if (result == FetchingCode.NoNetwork.ordinal()) {
					alert(mContext.getString(R.string.no_network));
				}
				
				mManualFetchingData = false;
			}
			
			if (result != FetchingCode.Success.ordinal()) {
				return;
			}
			
			mLatestUpadateDateTime = updateTime;
			mCurrExchangeRateArray = exchangeRateArray;
			
			mPrevUpdatedDateTime = prevUpdatedTime;
			mPreExchangeRateArray = prevExchangeRateArray;
			
			if (mPreExchangeRateArray == null) {
				mPrevUpdatedDateTime = "";
			}
			
			updateLastUpdatedTime(mLatestUpadateDateTime);
			
			if (mCurrAdapter != null) {
				mCurrAdapter.notifyDataSetChanged();	
			}
		}
	}
	
	private class ExchangeRateComparator implements Comparator<ExchangeRateItem> {
		@Override
		public int compare(ExchangeRateItem a, ExchangeRateItem b) {
			String codeA = a.getCurrencyCode();
			if (codeA != null) {
				if (codeA.equalsIgnoreCase("USD")) {
					return -1;
				}
				else if (codeA.equalsIgnoreCase("JPY")) {
					return -1;
				}
				else if (codeA.equalsIgnoreCase("EUR")) {
					return -1;
				}
				else if (codeA.equalsIgnoreCase("CHF")) {
					return -1;
				}
				else if (codeA.equalsIgnoreCase("GBP")) {
					return -1;
				}
			}
			
			String codeB = b.getCurrencyCode();
    	    return codeA.compareTo(codeB);
		}
	}
	
	@Override
	public void popoverViewWillShow(PopoverView view) {
		Log.i("POPOVER", "Will show");
		
		RelativeLayout detailInfo = view.getPopoverView();

		TextView preTimeTextView  = (TextView) detailInfo.findViewById(R.id.preTimeTextView);
		TextView preBuyTextView  = (TextView) detailInfo.findViewById(R.id.preBuyTextView);
		TextView preSellTextView  = (TextView) detailInfo.findViewById(R.id.preSellTextView);
		TextView preExchangeTextView  = (TextView) detailInfo.findViewById(R.id.preExchangeTextView);

		TextView curTimeTextView  = (TextView) detailInfo.findViewById(R.id.curTimeTextView);
		TextView curBuyTextView  = (TextView) detailInfo.findViewById(R.id.curBuyTextView);
		TextView curSellTextView  = (TextView) detailInfo.findViewById(R.id.curSellTextView);
		TextView curExchangeTextView  = (TextView) detailInfo.findViewById(R.id.curExchangeTextView);

		ExchangeRateItem currentData = mCurrExchangeRateArray.get(view.mRowIndex);
		
		ExchangeRateItem prevData  = null;
		if (mPreExchangeRateArray != null && view.mRowIndex < mPreExchangeRateArray.size()) {
			prevData = mPreExchangeRateArray.get(view.mRowIndex);	
		}

		//TODO not found pre update time
		// Previous gold price
		String dateTime = mPrevUpdatedDateTime;
			
		if (dateTime != null && dateTime.length() > 0) {
			dateTime = mContext.getString(R.string.before) + " " + Utilities.convertStringToDateString(dateTime, 
					Constant.UPDATED_DATE_TIME_FORMAT, Constant.CALLOUT_UPDATED_DATE_TIME_FORMAT);
		}
		else {
			dateTime = mContext.getString(R.string.before);
		}
		
//		String buyString = String.format("%.0f", curBuy);
//        if (buyString.equalsIgnoreCase("0") == false) {
//            holder.buy.setText(Utilities.formatNumber(buyString));
//		}
		
		preTimeTextView.setText(dateTime);
		
		// Current gold price
		dateTime = "";
		dateTime = mLatestUpadateDateTime;

		if (dateTime != null && dateTime.length() > 0) {
			dateTime = mContext.getString(R.string.current) + " " + Utilities.convertStringToDateString(dateTime, 
					Constant.UPDATED_DATE_TIME_FORMAT, Constant.CALLOUT_UPDATED_DATE_TIME_FORMAT);
		}
		else {
			dateTime = mContext.getString(R.string.before);
		}
		
		curTimeTextView.setText(dateTime);
		
		double curBuy = currentData.getBuy();
		double curSell = currentData.getSell();
		double curTransfer = currentData.getTransfer();
		double preBuy = 0;
		double preSell = 0;		
		double preTransfer = 0;
		
		if (prevData != null) {
			preBuy = prevData.getBuy();
			preSell = prevData.getSell();
			preTransfer = prevData.getTransfer();
		}		

		// Change value
		TextView buyValueChangeTextView = (TextView) detailInfo.findViewById(R.id.buyValueChangeTextView);
		TextView buyPercentChangeTextView = (TextView) detailInfo.findViewById(R.id.buyPercentChangeTextView);		
		TextView sellValueChangeTextView = (TextView) detailInfo.findViewById(R.id.sellValueChangeTextView);
		TextView sellPercentChangeTextView = (TextView) detailInfo.findViewById(R.id.sellPercentChangeTextView);
		TextView exchangeValueChangeTextView = (TextView) detailInfo.findViewById(R.id.exchangeValueChangeTextView);
		TextView exchangePercentChangeTextView = (TextView) detailInfo.findViewById(R.id.exchangePercentChangeTextView);
		TextView changeTextView = (TextView) detailInfo.findViewById(R.id.changeTextView);

		setValueTextViews(curBuy, preBuy, NUMBER_FORMAT, curBuyTextView, preBuyTextView, buyValueChangeTextView, buyPercentChangeTextView, null);
		setValueTextViews(curSell, preSell, NUMBER_FORMAT, curSellTextView, preSellTextView, sellValueChangeTextView, sellPercentChangeTextView, null);
		setValueTextViews(curTransfer, preTransfer, NUMBER_FORMAT, curExchangeTextView, preExchangeTextView, exchangeValueChangeTextView, exchangePercentChangeTextView, null);
		
		if (prevData == null) {
			changeTextView.setTextColor(color.black_pure);
		}
	}

	@Override
	public void popoverViewDidShow(PopoverView view) {
		Log.i("POPOVER", "Did show");
	}

	@Override
	public void popoverViewWillDismiss(PopoverView view) {
		Log.i("POPOVER", "Will dismiss");
	}

	@Override
	public void popoverViewDidDismiss(PopoverView view) {
		Log.i("POPOVER", "Did dismiss");
		mPopoverView = null;
	}
	
	private class ExchangedRateAdapter extends BaseAdapter {
		private Context mContext;
		private HashMap<String, Integer> mFlags = new HashMap<String, Integer>();
						
		public ExchangedRateAdapter(Context context, ArrayList<ExchangeRateItem> mArray,
				Handler mHandle) {
			super();
			this.mContext = context;
			
			mFlags.put("AUD", R.drawable.aud);
			mFlags.put("CAD", R.drawable.cad);
			mFlags.put("CHF", R.drawable.chf);
			mFlags.put("DKK", R.drawable.dkk);
			mFlags.put("EUR", R.drawable.eur);
			mFlags.put("GBP", R.drawable.gbp);
			mFlags.put("INR", R.drawable.inr);
			mFlags.put("JPY", R.drawable.jpy);
			mFlags.put("HKD", R.drawable.hkd);
			mFlags.put("KRW", R.drawable.krw);
			mFlags.put("KWD", R.drawable.kwd);
			mFlags.put("MYR", R.drawable.myr);
			mFlags.put("NOK", R.drawable.nok);
			mFlags.put("RUB", R.drawable.rub);
			mFlags.put("SAR", R.drawable.sar);
			mFlags.put("SEK", R.drawable.sek);
			mFlags.put("SGD", R.drawable.sgd);
			mFlags.put("THB", R.drawable.thb);
			mFlags.put("USD", R.drawable.usd);		
		}

		public int getCount() {
			if (mCurrExchangeRateArray == null) {
				return 0;
			}
			
			return mCurrExchangeRateArray.size();
		}

		public Object getItem(int position) {
			if (position >= mCurrExchangeRateArray.size()) {
				return null;
			}
			
			return mCurrExchangeRateArray.get(position);
		}

		public long getItemId(int position) {
			return position;
		}
		
		private RateHolder createChildHolder(View convertView) {
			RateHolder holder = new RateHolder();
			
			holder.title = (TextView) convertView.findViewById(R.id.currency_code_val);
			holder.flag = (ImageView)convertView.findViewById(R.id.flagImage);
			holder.buy = (TextView) convertView.findViewById(R.id.buy_val);
			holder.buyDiff = (TextView) convertView.findViewById(R.id.buy_diff);
			holder.buyPer = (TextView) convertView.findViewById(R.id.buy_per);
			holder.sell = (TextView) convertView.findViewById(R.id.sell_val);
			holder.sellDiff = (TextView) convertView.findViewById(R.id.sell_diff);
			holder.sellPer = (TextView) convertView.findViewById(R.id.sell_per);
			holder.transfer = (TextView) convertView.findViewById(R.id.transfer_val);
			holder.transferDiff = (TextView) convertView.findViewById(R.id.transfer_diff);
			holder.transferPer = (TextView) convertView.findViewById(R.id.transfer_per);
			holder.buyEmptyView = convertView.findViewById(R.id.buyEmptyView);
			holder.transferEmptyView = convertView.findViewById(R.id.transferEmptyView);
			holder.sellEmptyView = convertView.findViewById(R.id.sellEmptyView);
			
			return holder;
		}

		public View getView(final int position, View convertView, ViewGroup parent) {
			RateHolder holder;
			
			// Exchange Rate data
	        ExchangeRateItem item = mCurrExchangeRateArray.get(position);
	        
	        ExchangeRateItem preItem = null;
	        if (mPreExchangeRateArray != null && position < mPreExchangeRateArray.size()) {
	        	preItem = mPreExchangeRateArray.get(position);	
	        }
	        
	        if (convertView == null) {
	        	LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	        	
				final View view = inflater.inflate(R.layout.rate_item_row, null, false);

				holder = createChildHolder(view);
							
				view.setTag(holder);
				
				convertView = view;
			}
			else {			
				Object tagObject = convertView.getTag();
				if (tagObject != null && tagObject instanceof RateHolder) {
					holder = (RateHolder)tagObject;
				}
				else {
					holder = createChildHolder(convertView);
					convertView.setTag(holder);
				}
			}
     
	        String code = item.getCurrencyCode();
	        holder.title.setText(code);
	                
	        Integer imageId = mFlags.get(code);
	        if (imageId != null) {
	        	holder.flag.setBackgroundResource(imageId);
			}
	        
	        double curBuy = item.getBuy();
			double curSell = item.getSell();
			double curTransfer = item.getTransfer();
			double preBuy = 0;
			double preSell = 0;		
			double preTransfer = 0;
			
			if (preItem != null) {
				preBuy = preItem.getBuy();
				preSell = preItem.getSell();
				preTransfer = preItem.getTransfer();
			}
			
			setValueTextViews(curBuy, preBuy, NUMBER_FORMAT, holder.buy, holder.buyDiff, holder.buyPer, holder.buyEmptyView);
			setValueTextViews(curSell, preSell, NUMBER_FORMAT, holder.sell, holder.sellDiff, holder.sellPer, holder.sellEmptyView);
			setValueTextViews(curTransfer, preTransfer, NUMBER_FORMAT, holder.transfer, holder.transferDiff, holder.transferPer, holder.transferEmptyView);			
	        
	        convertView.setSelected(true);
	        return convertView; 
		}
		
		private class RateHolder {
			public TextView title = null;
			public ImageView flag = null;
			public TextView buy = null;
			public TextView sell = null;
			public TextView transfer = null;
			public TextView buyDiff = null;
			public TextView sellDiff = null;
			public TextView transferDiff = null;
			public TextView buyPer = null;
			public TextView sellPer = null;
			public TextView transferPer = null;			
			public View buyEmptyView = null;
			public View transferEmptyView = null;
			public View sellEmptyView = null;
		}
		
	}
}
